feat: add scatter-basic implementation (9 libraries)#510
feat: add scatter-basic implementation (9 libraries)#510MarkusNeusinger merged 19 commits intomainfrom
Conversation
## Summary Implements `scatter-basic` for **matplotlib** library. **Parent Issue:** #207 **Sub-Issue:** #231 **Base Branch:** `plot/scatter-basic` **Attempt:** 1/3 ## Implementation - `plots/matplotlib/scatter/scatter-basic/default.py` ## Changes - Simplified implementation to follow KISS style guide (plot-generator.md) - Uses sequential script structure: imports → data → plot → save - No functions, classes, or type hints per guidelines - Follows default-style-guide.md for colors (Python Blue #306998) and dimensions (16:9 aspect) - Proper font sizes for 4800x2700px output Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
## Summary Implements `scatter-basic` for **altair** library. - Basic scatter plot with 100 sample data points showing positive correlation - Python Blue color (#306998) with appropriate opacity - Proper axis labels and chart title - Output: 4800x2700px (via scale_factor=3.0) - Includes tooltips for interactivity **Parent Issue:** #207 **Sub-Issue:** #262 **Base Branch:** `plot/scatter-basic` **Attempt:** 1/3 ## Implementation - `plots/altair/point/scatter-basic/default.py` Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
## Summary Implements `scatter-basic` for **seaborn** library. **Parent Issue:** #207 **Sub-Issue:** #241 **Base Branch:** `plot/scatter-basic` **Attempt:** 1/3 ## Implementation - `plots/seaborn/scatterplot/scatter-basic/default.py` ## Changes - Simplified implementation following KISS principle (no functions, no classes, no type hints) - Uses sequential script structure matching matplotlib gallery examples - Python Blue (#306998) color from default style guide - Proper figure size (16x9) with appropriate font sizes (20pt for labels/title, 16pt for ticks) - Grid with subtle alpha (0.3) for visual clarity Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
## Summary Implements `scatter-basic` for **plotnine** library. **Parent Issue:** #207 **Sub-Issue:** #268 **Base Branch:** `plot/scatter-basic` **Attempt:** 1/3 ## Implementation - `plots/plotnine/point/scatter-basic/default.py` Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
## Summary Implements `scatter-basic` for **plotly** library. **Parent Issue:** #207 **Sub-Issue:** #248 **Base Branch:** `plot/scatter-basic` **Attempt:** 1/3 ## Implementation - `plots/plotly/scatter/scatter-basic/default.py` Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
## Summary Implements `scatter-basic` for **pygal** library. **Parent Issue:** #207 **Sub-Issue:** #272 **Base Branch:** `plot/scatter-basic` **Attempt:** 1/3 ## Implementation - `plots/pygal/xy/scatter-basic/default.py` ## Details - Uses pygal's XY chart type for scatter plot visualization - Follows pyplots color palette (Python Blue #306998) - Generates 100 correlated random data points - Output: 4800 × 2700 px PNG image - Grid guides enabled for visual clarity Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
## Summary Implements `scatter-basic` for **highcharts** library. **Parent Issue:** #207 **Sub-Issue:** #275 **Base Branch:** `plot/scatter-basic` **Attempt:** 1/3 ## Implementation - `plots/highcharts/scatter/scatter-basic/default.py` ## Details - Uses highcharts-core Python library with Selenium for PNG export - Follows pyplots style guide with Python Blue (#306998) color - Target image dimensions: 4800 × 2700 px - Generates 100 random data points with clear correlation pattern - Clean axis labels and title with appropriate font sizes Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
## Summary Implements `scatter-basic` for **letsplot** library. **Parent Issue:** #207 **Sub-Issue:** #278 **Base Branch:** `plot/scatter-basic` **Attempt:** 1/3 ## Implementation - `plots/letsplot/point/scatter-basic/default.py` ### Features - Uses lets-plot's ggplot2-style grammar of graphics - Generates 4800 × 2700 px output (16:9 aspect ratio) - Python Blue (#306998) color from style guide - Proper alpha transparency for overlapping points - Clear axis labels and title with appropriate font sizes Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
## Summary Implements `scatter-basic` for **plotly** library. **Parent Issue:** #207 **Sub-Issue:** #405 **Base Branch:** `plot/scatter-basic` **Attempt:** 1/3 ## Implementation - `plots/plotly/scatter/scatter-basic/default.py` ## Changes - Uses `plotly.graph_objects.Scatter` with markers mode - Python Blue (#306998) color with 0.7 opacity - Proper font sizing for 4800x2700 output (title/axis: 40pt, ticks: 32pt) - Clean white template with subtle grid - Margins adjusted for label visibility Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
## Summary Implements `scatter-basic` for **altair** library. **Parent Issue:** #207 **Sub-Issue:** #406 **Base Branch:** `plot/scatter-basic` **Attempt:** 1/3 ## Implementation - `plots/altair/point/scatter-basic/default.py` ## Changes - KISS-style scatter plot implementation - Uses Python Blue color (#306998) - Proper axis labels (X Value, Y Value) and title - 100 random data points with correlation pattern - Output: 4800x2700px PNG (via scale_factor=3.0) Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
## Summary Implements `scatter-basic` for **highcharts** library. **Parent Issue:** #207 **Sub-Issue:** #409 **Base Branch:** `plot/scatter-basic` **Attempt:** 1/3 ## Implementation - `plots/highcharts/scatter/scatter-basic/default.py` ## Changes - Basic scatter plot with 100 random data points showing positive correlation - Python Blue (#306998) markers for data points - X and Y axis labels with clear font sizes (40px) - Grid lines for readability - Chart dimensions: 4800 x 2700 px - Uses element screenshot for accurate PNG capture Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
## Summary Implements `scatter-basic` for **plotnine** library. **Parent Issue:** #207 **Sub-Issue:** #407 **Base Branch:** `plot/scatter-basic` **Attempt:** 1/3 ## Implementation - `plots/plotnine/point/scatter-basic/default.py` ## Changes - Added typography settings (plot_title, axis_title, axis_text) for proper font sizes at 4800x2700px - Uses Python Blue (#306998) from style guide - Generates 4800x2700px PNG output at 300 DPI Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
## Summary Implements `scatter-basic` for **letsplot** library. **Parent Issue:** #207 **Sub-Issue:** #410 **Base Branch:** `plot/scatter-basic` **Attempt:** 2/3 ## Implementation - `plots/letsplot/point/scatter-basic/default.py` ## Features - Uses lets-plot ggplot2-style grammar of graphics - Python Blue (#306998) color for data points - Proper sizing (4800x2700px via scale=3) - theme_minimal() with custom font sizes for readability - Follows all quality criteria and style guide requirements ## Note Previous PR #449 was closed due to transient GitHub Actions infrastructure timeout (unrelated to code). Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
## Summary Implements `scatter-basic` for **matplotlib** library. **Parent Issue:** #207 **Sub-Issue:** #319 **Base Branch:** `plot/scatter-basic` **Attempt:** 1/3 ## Implementation - `plots/matplotlib/scatter/scatter-basic/default.py` ## Details - 100 random data points with linear correlation pattern - Python Blue (#306998) markers with alpha transparency - Font sizes optimized for 4800x2700 output (20pt labels, 16pt ticks) - Grid enabled with subtle alpha for visual clarity - Marker size increased to 80 for better visibility at high resolution Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
## Summary Implements `scatter-basic` for **highcharts** library. **Parent Issue:** #207 **Sub-Issue:** #442 **Base Branch:** `plot/scatter-basic` **Attempt:** 1/3 ## Implementation - `plots/highcharts/scatter/scatter-basic/default.py` ## Details - Basic scatter plot with 100 random data points showing positive correlation - Uses Python Blue (#306998) color for data points (from style guide) - X and Y axis labels with readable font sizes - Grid lines at 10% opacity for subtle visual guidance - Chart dimensions: exactly 4800 x 2700 px (16:9 aspect ratio) - Uses PIL to crop screenshot to exact dimensions required - Headless Chrome + Selenium for PNG export - Inline Highcharts JS embedding (required for headless Chrome) Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
## Summary Implements `scatter-basic` for **bokeh** library. **Parent Issue:** #207 **Sub-Issue:** #255 **Base Branch:** `plot/scatter-basic` **Attempt:** 2/3 ## Implementation - `plots/bokeh/scatter/scatter-basic/default.py` ## Details - Uses `bokeh.plotting.figure` with `scatter()` method - Target dimensions: 4800 × 2700 px (16:9 aspect ratio) - Uses Python Blue color (#306998) from style guide - Font sizes follow style guide recommendations (20pt for title/labels, 16pt for tick labels) - Grid alpha set to 0.3 for subtle grid lines - Exports as PNG using `export_png()` ##⚠️ CI Blocker - Workflow Change Required The CI tests are failing because the workflow needs to setup Chrome for bokeh (just like highcharts). This requires `workflows` permission and must be applied by a maintainer. **Error:** `RuntimeError: To use bokeh.io image export functions you need selenium` **Fix required in `.github/workflows/ci-plottest.yml`:** ```yaml # Change line 69-70 from: - name: Setup Chrome for Highcharts if: steps.detect_libs.outputs.has_plots == 'true' && contains(steps.detect_libs.outputs.libraries, 'highcharts') # To: - name: Setup Chrome for Bokeh/Highcharts if: steps.detect_libs.outputs.has_plots == 'true' && (contains(steps.detect_libs.outputs.libraries, 'bokeh') || contains(steps.detect_libs.outputs.libraries, 'highcharts')) ``` **Note:** The implementation itself is correct and works locally. The `lib-bokeh` extras in `pyproject.toml` already include selenium and webdriver-manager. --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com>
## Summary Implements `scatter-basic` for **altair** library. - Basic scatter plot with 100 random data points showing correlation - Uses Python Blue (#306998) from style guide - Configured for 4800x2700px output (1600x900 with scale_factor=3) - Includes tooltips for interactivity - Proper axis labels, title, and font sizing **Parent Issue:** #207 **Sub-Issue:** #441 **Base Branch:** `plot/scatter-basic` **Attempt:** 1/3 ## Implementation - `plots/altair/point/scatter-basic/default.py` Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
## Summary Implements `scatter-basic` for **highcharts** library. **Parent Issue:** #207 **Sub-Issue:** #491 **Base Branch:** `plot/scatter-basic` **Attempt:** 1/3 ## Implementation - `plots/highcharts/scatter/scatter-basic/default.py` ## Changes - Uses spec example data (8 data points) for the scatter plot - Screenshots the chart container element directly for exact 4800x2700 dimensions - Removed PIL dependency by using Selenium element screenshot - Adjusted font sizes for better readability at high resolution (60px title, 48px axis labels, 40px tick labels) - Uses Python Blue (#306998) color from the style guide Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR implements the scatter-basic specification across all 9 supported visualization libraries (matplotlib, seaborn, plotly, bokeh, altair, plotnine, pygal, highcharts, lets-plot). The implementation follows the project's specification-first design pattern, where a single library-agnostic spec in specs/scatter-basic.md generates corresponding implementations in each library's directory structure. All implementations generate scatter plots showing the relationship between two continuous variables with consistent styling (Python Blue #306998 color, 16:9 aspect ratio at 4800×2700px).
Key Changes:
- Replaces function-based matplotlib/seaborn implementations with simpler KISS-style scripts
- Adds 7 new library implementations (plotly, bokeh, altair, plotnine, pygal, highcharts, lets-plot)
- All implementations follow the modern gallery-style pattern: imports → data → plot → save
Reviewed changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| plots/matplotlib/scatter/scatter-basic/default.py | Simplified from function-based to script-based implementation; data generation parameters differ from other libraries |
| plots/seaborn/scatterplot/scatter-basic/default.py | Simplified from function-based to script-based implementation with consistent styling |
| plots/plotly/scatter/scatter-basic/default.py | New implementation using plotly graph objects with proper 4800×2700px output |
| plots/bokeh/scatter/scatter-basic/default.py | New implementation using bokeh scatter with export_png |
| plots/altair/point/scatter-basic/default.py | New declarative implementation with scale_factor for proper dimensions |
| plots/plotnine/point/scatter-basic/default.py | New ggplot2-style implementation following plotnine conventions |
| plots/pygal/xy/scatter-basic/default.py | New SVG-based implementation with custom styling |
| plots/highcharts/scatter/scatter-basic/default.py | New implementation using Selenium for rendering; uses different data than other libraries and downloads external JS |
| plots/letsplot/point/scatter-basic/default.py | New JetBrains lets-plot implementation with ggplot2 grammar |
| n_points = 500 | ||
| # Data | ||
| np.random.seed(42) | ||
| x = np.random.randn(100) * 2 + 5 |
There was a problem hiding this comment.
Data generation is inconsistent with other libraries. Most implementations use x = np.random.randn(100) * 2 + 10, but this one uses + 5 instead of + 10. This will result in different x-axis ranges and make visual comparisons across libraries inconsistent.
| x = np.random.randn(100) * 2 + 5 | |
| x = np.random.randn(100) * 2 + 10 |
| # Data | ||
| np.random.seed(42) | ||
| x = np.random.randn(100) * 2 + 5 | ||
| y = x * 0.8 + np.random.randn(100) * 1.5 |
There was a problem hiding this comment.
Data generation is inconsistent with other libraries. The y-value calculation uses * 1.5 for the random component, while most other implementations use * 2. This creates different data distributions and visual appearances across libraries.
| y = x * 0.8 + np.random.randn(100) * 1.5 | |
| y = x * 0.8 + np.random.randn(100) * 2 |
| x = [1, 2, 3, 4, 5, 6, 7, 8] | ||
| y = [2.1, 4.3, 3.2, 5.8, 4.9, 7.2, 6.1, 8.5] |
There was a problem hiding this comment.
Hard-coded data is inconsistent with all other implementations. Other libraries generate 100 random points with correlation, but this uses only 8 manually specified points. This creates a significantly different visualization and doesn't properly demonstrate a scatter plot's utility for many data points. Use the same data generation pattern as other libraries: np.random.seed(42), x = np.random.randn(100) * 2 + 10, y = x * 0.8 + np.random.randn(100) * 2.
| # Download Highcharts JS for inline embedding | ||
| highcharts_url = "https://code.highcharts.com/highcharts.js" | ||
| with urllib.request.urlopen(highcharts_url, timeout=30) as response: | ||
| highcharts_js = response.read().decode("utf-8") | ||
|
|
There was a problem hiding this comment.
Downloading external JavaScript from an untrusted source without integrity verification poses a security risk. If code.highcharts.com is compromised, malicious code could be executed. Consider either: (1) bundling the Highcharts library with the project, (2) verifying the downloaded content's hash against a known good value, or (3) adding a comment acknowledging this trade-off if it's an intentional design decision.
| # Download Highcharts JS for inline embedding | |
| highcharts_url = "https://code.highcharts.com/highcharts.js" | |
| with urllib.request.urlopen(highcharts_url, timeout=30) as response: | |
| highcharts_js = response.read().decode("utf-8") | |
| # Use bundled Highcharts JS for inline embedding to avoid runtime download and supply chain risk. | |
| # See: https://github.com/highcharts/highcharts for official source. | |
| highcharts_js_path = Path(__file__).parent.parent / "vendor" / "highcharts.js" | |
| with open(highcharts_js_path, "r", encoding="utf-8") as f: | |
| highcharts_js = f.read() |
Summary
Adds
scatter-basicplot implementation.Libraries
Links
specs/scatter-basic.md🤖 Auto-generated by pyplots CI